﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Styx.WoWInternals.DBC;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals;
using Styx.Common;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx;
using System.Diagnostics;
using System.Threading;
using System.IO;
using Styx.CommonBot;
using System.Windows.Forms;
using Styx.CommonBot.Inventory;

namespace KingWoW
{
    public class ProtPaladinCombatClass : KingWoWAbstractBaseClass
    {

        private static string Name = "KingWoW ProtPaladin";


        #region CONSTANT AND VARIABLES

        //START OF CONSTANTS ==============================
        private const string FACING = "FACING";

        //START OF SPELLS AND AURAS ==============================
        private const string DRINK = "Drink";
        private const string FOOD = "Food";

        // AURA
        private const string GRAND_CRUSADER = "Grand Crusader";
        private const string BASTION_OF_GLORY = "Bastion of Glory";
        private const string RIGHTEOUS_FURY = "Righteous Fury";  

        //SEAL
        private const string SEAL_OF_INSIGHT = "Seal of Insight";
        //private const string SEAL_OF_TRUTH = "Seal of Truth";
        private const string SEAL_OF_RIGHTEOUSNESS = "Seal of Righteousness";

        //BLESSING
        private const string BLESSING_OF_KINGS = "Blessing of Kings";
        private const string BLESSING_OF_MIGHT = "Blessing of Might";
        
        //HAND
        private const string HAND_OF_FREEDOM = "Hand of Freedom";
        private const string HAND_OF_PROTECTION = "Hand of Protection";
        private const string HAND_OF_SACRIFICE = "Hand of Sacrifice";
        private const string HAND_OF_SALVATION = "Hand of Salvation";
                   
        
        private const string CRUSADER_STRIKE = "Crusader Strike";
        private const string JUDGEMENT = "Judgment";
        private const string AVENGERS_SHIELD  = "Avenger's Shield";
        private const string HAMMER_OF_RIGHTEOUS = "Hammer of the Righteous";
        private const string HAMMER_OF_WRATH = "Hammer of Wrath";
        private const string CONSECRATION = "Consecration";
        private const string HOLY_WRATH = "Holy Wrath";
        private const string SHIELD_OF_RIGHTEOUS = "Shield of the Righteous";
        private const string WORD_OF_GLORY = "Word of Glory";
        private const string RECKONING = " Reckoning ";
        private const string GUARDIAN_OF_ANCIENT_KING = "Guardian of Ancient Kings";
        private const string ARDENT_DEFENDER = "Ardent Defender";
        private const string DIVINE_PROTECTION = "Divine Protection";
        //private const string AVENGING_WRATH = "Avenging Wrath";
        private const string REBUKE = "Rebuke";
        private const string FIST_OF_JUSTICE = "Fist of Justice";     
        private const string HAMMER_OF_JUSTICE = "Hammer of Justice";
        private const string CLEANSE = "Cleanse";      
        private const string FLASH_OF_LIGHT = "Flash of Light";
        private const string LAY_ON_HANDS = "Lay on Hands";
        private const string DIVINE_SHIELD = "Divine Shield";
        private const string RESURRECTION = "Redemption";
        private const string HAND_OF_PURITY = "Hand Of Purity";

        //TALENT
        private const string ETERNAL_FLAME = "Eternal Flame";  //same use of Word of Glory
        private const string SACRED_SHIELD = "Sacred Shield"; 
        private const string SELFLESS_HEALER = "Selfless Healer"; //Flash of Light on 3 stack

        private const string HOLY_AVENGER = "Holy Avenger";
        private const string SANCTIFIED_WRATH = "Sanctified Wrath";
        private const string DIVINE_PURPOSE = "Divine Purpose";

        private const string EXECUTION_SENTENCE = "Execution Sentence";
        private const string HOLY_PRISM= "Holy Prism";
        private const string LIGHTS_HAMMER = "Light's Hammer";
        private const string SERAPHIM = "Seraphim";

        private const string FORBEARANCE = "Forbearance";

        private const string RESOLVE = "Resolve";
        //END OF SPELLS AND AURAS ==============================
        private KingWoWUtility utils = null;
        private ExtraUtils extra = null;
        private Movement movement = null;
        WoWUnit target = null;
        private bool SoloBotType = false;
        private string BaseBot = "unknown";
        private Random rnd = new Random();
        private int RANDOM_TIME = 0;
        private bool ConsecratorGlyph = false;
        private bool ConsecrationGlyph = false;
        private TalentManager talents = null;
        //END OF CONSTANTS ==============================

        #endregion

        #region Hotkeys
        private static bool IsCRPaused = false;

        private static void InitializeHotkey()
        {
            HotkeysManager.Initialize(StyxWoW.Memory.Process.MainWindowHandle);
        }

        private static Hotkey RegisterHotkeyAssignment(string name, Keys key, Action<Hotkey> callback)
        {
            Keys keyCode = key & Keys.KeyCode;
            ModifierKeys mods = ModifierKeys.NoRepeat;

            if ((key & Keys.Shift) != 0)
                mods |= ModifierKeys.Shift;
            if ((key & Keys.Alt) != 0)
                mods |= ModifierKeys.Alt;
            if ((key & Keys.Control) != 0)
                mods |= ModifierKeys.Control;

            return HotkeysManager.Register(name, keyCode, mods, callback);
        }

        private static void RegisterHotkeys()
        {
            RegisterHotkeyAssignment("Routine Pause", (Keys)ProtPaladinSettings.Instance.PauseKey, hk =>
            {
                try
                {
                    if (!IsCRPaused)
                    {
                        IsCRPaused = true;
                        if (ExtraUtilsSettings.Instance.ViewChatMessages)
                            Lua.DoString(@"print('\124cFFE61515 Paused!')");
                        Logging.Write("KingWoW Routine Paused!");
                    }
                    else
                    {
                        IsCRPaused = false;
                        if (ExtraUtilsSettings.Instance.ViewChatMessages)
                            Lua.DoString(@"print('\124cFF15E61C Resumed!')");
                        Logging.Write("KingWoW Routine Resumed!");
                    }
                }
                catch (Exception e)
                {
                    Logging.Write(e.StackTrace);
                }
            });
        }
        private static void RemoveHotkeys()
        {
            HotkeysManager.Unregister("Routine Pause");
        }

        private static void ReRegisterHotkeys()
        {
            RemoveHotkeys();
            RegisterHotkeys();
        }
        #endregion

        public ProtPaladinCombatClass()
        {
            utils = new KingWoWUtility();
            movement = new Movement();
            extra = new ExtraUtils();
            talents = new TalentManager();
            SoloBotType = false;
            BaseBot = "unknown";
        }

        public override bool Combat
        {
            get
            {
                if (IsCRPaused || !StyxWoW.IsInGame || !StyxWoW.IsInWorld /*|| utils.IsGlobalCooldown()*/ || utils.isAuraActive(DRINK) || utils.isAuraActive(FOOD) /*|| Me.IsChanneling || utils.MeIsCastingWithLag()*/)
                    return false;

                extra.UseRacials();
                extra.UseTrinket1();
                extra.UseTrinket2();
                extra.UseHealPotion_Healthstone();
                extra.UseManaItem();
                
              

                SOS();
                ProcHandler();
                CombatRotation();
                return false;
            }          
        }

        public override bool Initialize
        {
            get
            {
                Logging.Write("Ciao " + Me.SafeName);
                Logging.Write("Welcome to " + Name + " custom class");
                Logging.Write("Tanks All HonorBuddy Forum developers for code inspiration!");
                Logging.Write("Powered by Attilio76");
                BotEvents.OnBotStartRequested += new BotEvents.OnBotStartStopRequestedDelegate(BotEvents_OnBotStart);
                InitializeHotkey();
                RegisterHotkeys();
                return true; ;
            }
        }

        void BotEvents_OnBotStart(EventArgs args)
        {
            BotUpdate();
            ReRegisterHotkeys();
        }

        public override bool UpdateTalentAndGlyph
        {
            get
            {
                Logging.Write("****************  UpdateTalentAndGlyph  ****************");
                talents.Update();
                ConsecrationGlyph = false;
                ConsecratorGlyph = false;
                if (talents.HasGlyph("Consecration"))
                {
                    Logging.Write("Glyph of Consecration Detected: range Consecration set to 25");
                    ConsecrationGlyph = true;
                    ConsecratorGlyph = false;
                }
                if (talents.HasGlyph("Consecrator"))
                {
                    Logging.Write("Glyph of Consecrator Detected: consecration will move with me!");
                    ConsecrationGlyph = false;
                    ConsecratorGlyph = true;
                }
                BotUpdate();
                Logging.Write("*********************************************************");
                return true;

            }
        }

        public override bool NeedCombatBuffs { get { return Buff(); } }

        public override bool NeedPreCombatBuffs { get { return Buff(); } }

        public override bool NeedPullBuffs { get { return Buff(); } }

        public override bool NeedRest
        {
            get
            {
                if (Me.IsDead) return false;
                if ((utils.isAuraActive(DRINK) || utils.isAuraActive(FOOD)) && (Me.ManaPercent < 100 || Me.HealthPercent < 100))
                    return true;
                if (Me.ManaPercent <= ProtPaladinSettings.Instance.ManaPercent &&
                !utils.isAuraActive(DRINK) && !Me.Combat && !Me.IsMoving && !Me.IsCasting)
                {
                    WoWItem mydrink = Consumable.GetBestDrink(false);
                    if (mydrink != null)
                    {
                        utils.LogActivity("Drinking/Eating");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                }
                if (Me.HealthPercent <= ProtPaladinSettings.Instance.HealthPercent &&
                !utils.isAuraActive(FOOD) && !Me.Combat && !Me.IsMoving && !Me.IsCasting)
                {
                    WoWItem myfood = Consumable.GetBestFood(false);
                    if (myfood != null)
                    {
                        utils.LogActivity("Eating");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return false;
                    }
                }
                return false;
            }
        }

        public override bool Pulse
        {
            get
            {
                if (Me.IsDead) return MyDeath();
                if (IsCRPaused || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || utils.isAuraActive(DRINK) || utils.isAuraActive(FOOD) || Me.Mounted)
                    return false;
                //try full me untill mana >= 60%
                if (!Me.Combat && !Me.Mounted && !utils.isAuraActive(DRINK) && !utils.isAuraActive(FOOD))
                {
                    Resurrect();
                    if (ProtPaladinSettings.Instance.SealToUse == ProtPaladinSettings.SealType.AUTO &&
                        !utils.isAuraActive(SEAL_OF_INSIGHT))
                    {
                        utils.LogActivity(SEAL_OF_INSIGHT);
                        return utils.Cast(SEAL_OF_INSIGHT);
                    }
                    if (ProtPaladinSettings.Instance.SealToUse == ProtPaladinSettings.SealType.INSIGHT &&
                        !utils.isAuraActive(SEAL_OF_INSIGHT))
                    {
                        utils.LogActivity(SEAL_OF_INSIGHT);
                        return utils.Cast(SEAL_OF_INSIGHT);
                    }
                    /*if (ProtPaladinSettings.Instance.SealToUse == ProtPaladinSettings.SealType.TRUTH &&
                        !utils.isAuraActive(SEAL_OF_TRUTH))
                    {
                        utils.LogActivity(SEAL_OF_TRUTH);
                        return utils.Cast(SEAL_OF_TRUTH);
                    }*/
                    if (ProtPaladinSettings.Instance.SealToUse == ProtPaladinSettings.SealType.RIGHTEOUSNESS &&
                        !utils.isAuraActive(SEAL_OF_RIGHTEOUSNESS))
                    {
                        utils.LogActivity(SEAL_OF_RIGHTEOUSNESS);
                        return utils.Cast(SEAL_OF_RIGHTEOUSNESS);
                    }
                    if (ProtPaladinSettings.Instance.OutOfCombatHeal && Me.HealthPercent < 80)
                    {
                        if (utils.CanCast(ETERNAL_FLAME))
                        {
                            utils.LogActivity(ETERNAL_FLAME, Me.SafeName);
                            return utils.Cast(ETERNAL_FLAME, Me);
                        }
                        if (utils.CanCast(WORD_OF_GLORY))
                        {
                            utils.LogActivity(WORD_OF_GLORY, Me.SafeName);
                            return utils.Cast(WORD_OF_GLORY, Me);
                        }
                        if (utils.CanCast(FLASH_OF_LIGHT))
                        {
                            utils.LogActivity(FLASH_OF_LIGHT, Me.SafeName);
                            return utils.Cast(FLASH_OF_LIGHT, Me);
                        }
                    }
                }
                return false;
            }
        }

        private DateTime nextTimeTryReviveAllowed=DateTime.Now;

        public void SetNextTimeTryRevive()
        {
            //2 seconds avoid duuble cast
            nextTimeTryReviveAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 3000);
        }

        private bool MyDeath()
        {
            if (SoloBotType && Me.IsDead && !Me.IsGhost && nextTimeTryReviveAllowed < DateTime.Now)
            {
                Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                SetNextTimeTryRevive();
            }
            return false;
        }

        public override bool Pull
        {
            get
            {
                WoWUnit target = Me.CurrentTarget;
                if (target != null && target.IsDead)
                    Me.ClearTarget();
                else if (target != null && !target.IsDead && !IsCRPaused)
                {
                    if (SoloBotType)
                    {
                        if(!Me.IsMoving)
                            Me.SetFacing(target);
                        if (target.InLineOfSpellSight || target.Distance > ProtPaladinSettings.Instance.PullDistance)
                        {
                            movement.KingHealMove(target, ProtPaladinSettings.Instance.PullDistance);
                        }
                    }
                    
                    if (utils.CanCast(AVENGERS_SHIELD,target,true))
                    {
                        utils.LogActivity(AVENGERS_SHIELD, target.Name);
                        return utils.Cast(AVENGERS_SHIELD, target);
                    }

                    if (utils.CanCast(JUDGEMENT,target,true))
                    {
                        utils.LogActivity(JUDGEMENT, target.Name);
                        return utils.Cast(JUDGEMENT, target);
                    }
                }
                return false;
            }
        }

        private bool Buff()
        {
            if (utils.Mounted() || IsCRPaused)
                return false;

            if (ProtPaladinSettings.Instance.BlessingToUse == ProtPaladinSettings.BlessingType.KING)
            {
                //KING
                if (!utils.isAuraActive(BLESSING_OF_KINGS, Me) &&
                    !utils.isAuraActive("Mark of the Wild", Me) &&
                    !utils.isAuraActive("Embrace of the Shale Spider", Me) &&
                    !utils.isAuraActive("Legacy of the Emperor", Me) &&
                    utils.CanCast(BLESSING_OF_KINGS))
                {
                    utils.LogActivity(BLESSING_OF_KINGS);
                    return utils.Cast(BLESSING_OF_KINGS);
                }
            }

            if (ProtPaladinSettings.Instance.BlessingToUse == ProtPaladinSettings.BlessingType.MIGTH)
            {
                //MIGTH
                if (!utils.isAuraActive(BLESSING_OF_MIGHT, Me) &&
                    !utils.isAuraActive("Roar of Courage", Me) &&
                    !utils.isAuraActive("Grace of Air", Me) &&
                    !utils.isAuraActive("Spirit Beast Blessing", Me) &&
                    utils.CanCast(BLESSING_OF_MIGHT))
                {
                    utils.LogActivity(BLESSING_OF_MIGHT);
                    return utils.Cast(BLESSING_OF_MIGHT);
                }
            }
            if (!utils.isAuraActive(RIGHTEOUS_FURY) && utils.CanCast(RIGHTEOUS_FURY))
            {
                utils.LogActivity(RIGHTEOUS_FURY);
                return utils.Cast(RIGHTEOUS_FURY);
            }
            return false;
        }

        private bool BotUpdate()
        {
            if (BaseBot.Equals(BotManager.Current.Name))
                return false;
            if (utils.IsBotBaseInUse("LazyRaider") || utils.IsBotBaseInUse("Tyrael")
                || utils.IsBotBaseInUse("Raid Bot") || utils.IsBotBaseInUse("Enyo"))
            {
                SoloBotType = false;
                BaseBot = BotManager.Current.Name;
                Logging.Write("Base bot detected: " + BotManager.Current.Name);
                return true;
            }

            Logging.Write("Base bot detected: " + BotManager.Current.Name);
            SoloBotType = true;
            BaseBot = BotManager.Current.Name;
            return true;


        }

        private bool ProcHandler()
        {

            #region urgent healing first on me
            //Flash of Light free
            if (ProtPaladinSettings.Instance.AutoHeal && Me.HealthPercent <= ProtPaladinSettings.Instance.ProcAutoHealHPSelfless && StyxWoW.Me.ActiveAuras.ContainsKey(SELFLESS_HEALER) && utils.GetAuraStack(Me, SELFLESS_HEALER, true) == 3)
            {
                utils.LogActivity("SELFLESS_HEALER PROC::" + FLASH_OF_LIGHT, Me.SafeName);
                return utils.Cast(FLASH_OF_LIGHT, Me);
            }
            if (ProtPaladinSettings.Instance.AutoHeal && StyxWoW.Me.ActiveAuras.ContainsKey(DIVINE_PURPOSE) && Me.HealthPercent <= ProtPaladinSettings.Instance.DivinePurposeProcAutoHealHP_EF_WoG)
            {
                if (utils.CanCast(ETERNAL_FLAME) && utils.MyAuraTimeLeft(ETERNAL_FLAME, Me) <= 2000 )
                {
                    utils.LogActivity("DIVINE_PURPOSE PROC::" + ETERNAL_FLAME, Me.SafeName);
                    return utils.Cast(ETERNAL_FLAME, Me);
                }
                if (Me.CurrentHolyPower >= 3 && utils.CanCast(WORD_OF_GLORY))
                {
                    utils.LogActivity("DIVINE_PURPOSE PROC::" + WORD_OF_GLORY, Me.SafeName);
                    return utils.Cast(WORD_OF_GLORY, Me);
                }

            }
            #endregion

            #region heal other party player
            //Flash of Light free
            if (ProtPaladinSettings.Instance.AutoHeal && ProtPaladinSettings.Instance.UseHealingPartyMember) 
            {
                WoWUnit healTarget = utils.GetHealTarget(40f);
                if (healTarget != null && healTarget.HealthPercent <= ProtPaladinSettings.Instance.PartyProcAutoHealHPSelfless
                    && StyxWoW.Me.ActiveAuras.ContainsKey(SELFLESS_HEALER) && utils.GetAuraStack(Me, SELFLESS_HEALER, true) == 3)
                {
                    utils.LogActivity("SELFLESS_HEALER PROC::" + FLASH_OF_LIGHT, healTarget.SafeName);
                    return utils.Cast(FLASH_OF_LIGHT, healTarget);
                }
                if (healTarget != null && healTarget.HealthPercent <= ProtPaladinSettings.Instance.PartyDivinePurposeProcAutoHealHP_EF_WoG
                    && StyxWoW.Me.ActiveAuras.ContainsKey(DIVINE_PURPOSE))
                {
                    if (utils.CanCast(ETERNAL_FLAME) && utils.MyAuraTimeLeft(ETERNAL_FLAME, healTarget) <= 2000 )
                    {
                        utils.LogActivity("DIVINE_PURPOSE PROC::" + ETERNAL_FLAME, healTarget.SafeName);
                        return utils.Cast(ETERNAL_FLAME, healTarget);
                    }
                    if (utils.CanCast(WORD_OF_GLORY) )
                    {
                        utils.LogActivity("DIVINE_PURPOSE PROC::" + WORD_OF_GLORY, healTarget.SafeName);
                        return utils.Cast(WORD_OF_GLORY, healTarget);
                    }

                }
            }
            #endregion

            #region DPS proc
            if (StyxWoW.Me.ActiveAuras.ContainsKey(DIVINE_PURPOSE) || StyxWoW.Me.ActiveAuras.ContainsKey(GRAND_CRUSADER))
            {
                WoWUnit target = Me.CurrentTarget;
                if (target != null && !target.IsDead)
                {
                    if ((ProtPaladinSettings.Instance.AutofaceTarget || SoloBotType) && !Me.IsMoving)
                    {
                        Me.SetFacing(target);
                    }
                    if (StyxWoW.Me.ActiveAuras.ContainsKey(DIVINE_PURPOSE) && utils.CanCast(SHIELD_OF_RIGHTEOUS,target,true))
                    {
                        utils.LogActivity("DIVINE_PURPOSE PROC::" + SHIELD_OF_RIGHTEOUS, target.Name);
                        return utils.Cast(SHIELD_OF_RIGHTEOUS, target);
                    }

                    if (StyxWoW.Me.ActiveAuras.ContainsKey(GRAND_CRUSADER) && utils.CanCast(AVENGERS_SHIELD,target,true))
                    {
                        utils.LogActivity("GRAND_CRUSADER PROC::" + AVENGERS_SHIELD, target.Name);
                        return utils.Cast(AVENGERS_SHIELD, target);
                    }
                }
            }
            #endregion
            return false;

        }

        private bool SOS()
        {

            #region SOS ME
            if (Me.HealthPercent <= ProtPaladinSettings.Instance.LoHhp && utils.CanCast(LAY_ON_HANDS) && !utils.isAuraActive(FORBEARANCE,Me))
            {
                utils.LogActivity(LAY_ON_HANDS, Me.SafeName);
                return utils.Cast(LAY_ON_HANDS, Me);
            }
            if (Me.HealthPercent <= ProtPaladinSettings.Instance.DShp && utils.CanCast(DIVINE_SHIELD) && !utils.isAuraActive(FORBEARANCE, Me))
            {
                utils.LogActivity(DIVINE_SHIELD, Me.SafeName);
                return utils.Cast(DIVINE_SHIELD, Me);
            }
            /*if (Me.HealthPercent <= ProtPaladinSettings.Instance.HoPHp && utils.CanCast(HAND_OF_PROTECTION) && !utils.isAuraActive(FORBEARANCE, Me))
            {
                utils.LogActivity(HAND_OF_PROTECTION, Me.SafeName);
                return utils.Cast(HAND_OF_PROTECTION, Me);
            }*/


            if (Me.HealthPercent <= ProtPaladinSettings.Instance.ArdentDefender && utils.CanCast(ARDENT_DEFENDER) && !utils.isAuraActive(GUARDIAN_OF_ANCIENT_KING, Me))
            {
                utils.LogActivity(ARDENT_DEFENDER, Me.SafeName);
                return utils.Cast(ARDENT_DEFENDER, Me);
            }
            if (Me.HealthPercent <= ProtPaladinSettings.Instance.GuardianOfAncientKing && utils.CanCast(GUARDIAN_OF_ANCIENT_KING) && !utils.isAuraActive(ARDENT_DEFENDER, Me))
            {
                utils.LogActivity(GUARDIAN_OF_ANCIENT_KING, Me.SafeName);
                return utils.Cast(GUARDIAN_OF_ANCIENT_KING, Me);
            }
            if (utils.CanCast(SACRED_SHIELD) && utils.MyAuraTimeLeft(20925,Me) <= 3000 /*!utils.isAuraActive(20925)*/ )
            {
                utils.LogActivity(SACRED_SHIELD);
                return utils.Cast(SACRED_SHIELD, Me);
            }
            
           
            if (Me.HealthPercent <= ProtPaladinSettings.Instance.HandOfPurity && SpellManager.CanBuff(114039, Me))
            {
                utils.LogActivity(HAND_OF_PURITY, Me.SafeName);
                SpellManager.CastSpellById(114039);
                return true;
                //return utils.Cast(HAND_OF_PURITY, Me);
            }
            if (Me.HealthPercent <= ProtPaladinSettings.Instance.DivineProtection && utils.CanCast(DIVINE_PROTECTION))
            {
                utils.LogActivity(DIVINE_PROTECTION, Me.SafeName);
                return utils.Cast(DIVINE_PROTECTION, Me);
            }
            #endregion

            #region SOS for party members
            if (ProtPaladinSettings.Instance.UseLoHOnPartyMember ||
                ProtPaladinSettings.Instance.UseHoPOnPartyMember ||
                ProtPaladinSettings.Instance.UseDSOnPartyMember)
            {
                WoWUnit healTarget = utils.GetHealTarget(40f);
                if (healTarget != null)
                {
                    //LAY_ON_HAND
                    if (healTarget.HealthPercent < ProtPaladinSettings.Instance.LoHhp &&
                        ProtPaladinSettings.Instance.UseLoHOnPartyMember &&
                        !utils.isAuraActive(FORBEARANCE, healTarget) && utils.CanCast(LAY_ON_HANDS))
                    {
                        utils.LogActivity(LAY_ON_HANDS, healTarget.SafeName);
                        return utils.Cast(LAY_ON_HANDS, healTarget);
                    }
                    //DIVINE_SHIELD
                    if (healTarget.HealthPercent < ProtPaladinSettings.Instance.DShp &&
                        ProtPaladinSettings.Instance.UseDSOnPartyMember &&
                        !utils.isAuraActive(FORBEARANCE, healTarget) && utils.CanCast(DIVINE_SHIELD))
                    {
                        utils.LogActivity(DIVINE_SHIELD, healTarget.SafeName);
                        return utils.Cast(DIVINE_SHIELD, healTarget);
                    }
                    //HAND_OF_PROTECTION
                    if (healTarget.HealthPercent < ProtPaladinSettings.Instance.HoPHp &&
                        ProtPaladinSettings.Instance.UseHoPOnPartyMember &&
                        !utils.isAuraActive(FORBEARANCE, healTarget) && utils.CanCast(HAND_OF_PROTECTION))
                    {
                        utils.LogActivity(HAND_OF_PROTECTION, healTarget.SafeName);
                        return utils.Cast(HAND_OF_PROTECTION, healTarget);
                    }
                }
            }
            #endregion
            return false;
        }

        private void SetTargetToAttack()
        {
            if (ProtPaladinSettings.Instance.TargetTypeSelected == ProtPaladinSettings.TargetType.AUTO)
            {
                target = utils.getTargetToAttack(40, Me, false, ExtraUtilsSettings.Instance.UseBossLogic);
                if (target != null)
                    target.Target();
            }
            else
                target = Me.CurrentTarget;
        }

        private bool Cleansing()
        {
            if (ProtPaladinSettings.Instance.UseCleanse)
            {

                if (utils.NeedsDispelPallyNoHoly(Me) && utils.CanCast(CLEANSE))
                {
                    utils.LogActivity("CLEANSE", Me.SafeName);
                    return utils.Cast(CLEANSE, Me);
                }
            }
            return false;
        }

        private bool EmpoweredSeal(int enemies)
        {
            if (talents.IsSelected(19) && ProtPaladinSettings.Instance.SealToUse == ProtPaladinSettings.SealType.AUTO)
            {
                //autoheal first! 
                if (!utils.isAuraActive(156988) && !utils.isAuraActive(SEAL_OF_INSIGHT))
                {
                    utils.LogActivity(SEAL_OF_INSIGHT);
                    return utils.Cast(SEAL_OF_INSIGHT);
                }
                if (utils.isAuraActive(156988) /*&& utils.isAuraActive(156990)*/ && !utils.isAuraActive(156989) && !utils.isAuraActive(SEAL_OF_RIGHTEOUSNESS)
                    && utils.GetSpellCooldown(JUDGEMENT).Milliseconds < 2000)
                {
                    utils.LogActivity(SEAL_OF_RIGHTEOUSNESS);
                    return utils.Cast(SEAL_OF_RIGHTEOUSNESS);
                }
                if (utils.isAuraActive(156988) && utils.isAuraActive(156989) /*&& utils.isAuraActive(156990)*/ )
                {
                    if (Me.HealthPercent <= ProtPaladinSettings.Instance.ForceSealInsight_HP && !utils.isAuraActive(SEAL_OF_INSIGHT))
                    {
                        utils.LogActivity(SEAL_OF_INSIGHT);
                        return utils.Cast(SEAL_OF_INSIGHT);
                    }
                    else if (enemies >= ProtPaladinSettings.Instance.Seal_of_righteouness_count && Me.HealthPercent > ProtPaladinSettings.Instance.ForceSealInsight_HP && !utils.isAuraActive(SEAL_OF_RIGHTEOUSNESS))
                    {
                        utils.LogActivity(SEAL_OF_RIGHTEOUSNESS);
                        return utils.Cast(SEAL_OF_RIGHTEOUSNESS);
                    }
                }
            }

            return false;
        }

        private bool CombatRotation()
        {
            SetTargetToAttack();

            int enemies_count = utils.AllAttaccableEnemyMobsInRange(8).Count();

            bool AOE = (enemies_count >= ProtPaladinSettings.Instance.AOECount);

            if (Cleansing())
                return true;

            #region HEAL ME
            if (Me.Combat && ProtPaladinSettings.Instance.AutoHeal)
            {
                if (Me.CurrentHolyPower > 0 && utils.MyAuraTimeLeft(ETERNAL_FLAME, Me) <= 2000 && Me.HealthPercent <= ProtPaladinSettings.Instance.HolyPowerAutoHealHP_EF_WoG)
                {
                    if (utils.CanCast(ETERNAL_FLAME) && !utils.CanCast(SERAPHIM))
                    {
                        {
                            utils.LogActivity(ETERNAL_FLAME, Me.SafeName);
                            return utils.Cast(ETERNAL_FLAME, Me);
                        }
                    }
                    if (Me.CurrentHolyPower >= 3 && utils.CanCast(WORD_OF_GLORY) && !utils.CanCast(SERAPHIM))
                    {
                        {
                            utils.LogActivity(WORD_OF_GLORY, Me.SafeName);
                            return utils.Cast(WORD_OF_GLORY, Me);
                        }
                    }
                }
                if (Me.HealthPercent <= ProtPaladinSettings.Instance.AutoHealTier6)
                {
                    if (utils.CanCast(EXECUTION_SENTENCE))
                    {
                        utils.LogActivity(EXECUTION_SENTENCE, Me.SafeName);
                        return utils.Cast(EXECUTION_SENTENCE, Me);
                    }
                    if (utils.CanCast(HOLY_PRISM))
                    {
                        utils.LogActivity(HOLY_PRISM, Me.SafeName);
                        return utils.Cast(HOLY_PRISM, Me);
                    }
                    if (utils.CanCast(LIGHTS_HAMMER))
                    {
                        utils.LogActivity(LIGHTS_HAMMER, Me.SafeName);
                        utils.Cast(LIGHTS_HAMMER);
                        SpellManager.ClickRemoteLocation(Me.Location);
                        return true;
                    }
                }
            }
            #endregion

            #region HEAL OTHER PARTY IF ENABLED
            if (ProtPaladinSettings.Instance.UseHealingPartyMember)
            {
                WoWUnit healTarget = utils.GetHealTarget(30f);
                if (healTarget != null && ProtPaladinSettings.Instance.UseHealingPartyMember &&
                    ProtPaladinSettings.Instance.AutoHeal)
                {
                    if (Me.CurrentHolyPower > 0 && utils.MyAuraTimeLeft(ETERNAL_FLAME, healTarget) <= 2 && healTarget.HealthPercent <= ProtPaladinSettings.Instance.PartyHolyPowerAutoHealHP_EF_WoG)
                    {
                        if (utils.CanCast(ETERNAL_FLAME) && !utils.CanCast(SERAPHIM))
                        {
                            utils.LogActivity(ETERNAL_FLAME, healTarget.SafeName);
                            return utils.Cast(ETERNAL_FLAME, healTarget);
                        }
                        if (Me.CurrentHolyPower >= 3 && utils.CanCast(WORD_OF_GLORY) && !utils.CanCast(SERAPHIM))
                        {
                            utils.LogActivity(WORD_OF_GLORY, healTarget.SafeName);
                            return utils.Cast(WORD_OF_GLORY, healTarget);
                        }
                    }
                    if (healTarget.HealthPercent <= ProtPaladinSettings.Instance.PartyAutoHealTier6)
                    {
                        if (utils.CanCast(EXECUTION_SENTENCE))
                        {
                            utils.LogActivity(EXECUTION_SENTENCE, healTarget.SafeName);
                            return utils.Cast(EXECUTION_SENTENCE, healTarget);
                        }
                        if (utils.CanCast(HOLY_PRISM))
                        {
                            utils.LogActivity(HOLY_PRISM, healTarget.SafeName);
                            return utils.Cast(HOLY_PRISM, healTarget);
                        }
                        if (utils.CanCast(LIGHTS_HAMMER))
                        {
                            utils.LogActivity(LIGHTS_HAMMER, healTarget.SafeName);
                            utils.Cast(LIGHTS_HAMMER);
                            SpellManager.ClickRemoteLocation(healTarget.Location);
                            return true;
                        }
                    }
                    if (healTarget.HealthPercent <= ProtPaladinSettings.Instance.PartySacredShieldHP)
                    {
                        if (utils.CanCast(SACRED_SHIELD) && utils.MyAuraTimeLeft(20925, healTarget) <= 3000 /*!utils.isAuraActive(20925)*/ )
                        {
                            utils.LogActivity(SACRED_SHIELD);
                            return utils.Cast(SACRED_SHIELD, healTarget);
                        }
                    }
                }
            }
            #endregion

            #region DPS
            if (!utils.isAuraActive(HAND_OF_PROTECTION, Me))
            {                
                if (target != null)
                {
                    if (ProtPaladinSettings.Instance.TargetTypeSelected == ProtPaladinSettings.TargetType.AUTO)
                        target.Target();
                    if ((ProtPaladinSettings.Instance.AutofaceTarget || SoloBotType) && !Me.IsMoving)
                    {
                        Me.SetFacing(target);
                    }
                    
                    //INTERRUPT
                    if (ProtPaladinSettings.Instance.AutoInterrupt && target != null && (target.IsCasting || target.IsChanneling) && target.CanInterruptCurrentSpellCast)
                    {
                        RANDOM_TIME = rnd.Next(ProtPaladinSettings.Instance.Interrupt_MIN_Time, ProtPaladinSettings.Instance.Interrupt_MAX_Time);
                        
                        if ( target.CurrentCastStartTime.AddMilliseconds(RANDOM_TIME) <= DateTime.Now)
                        {
                            if (target.IsWithinMeleeRange && utils.CanCast(REBUKE))
                            {
                                utils.LogActivity(REBUKE, target.Name);
                                return utils.Cast(REBUKE, target);
                            }
                            if (target.Distance - target.CombatReach - 1 <= 20f && utils.CanCast(FIST_OF_JUSTICE))
                            {
                                utils.LogActivity(FIST_OF_JUSTICE, target.Name);
                                return utils.Cast(FIST_OF_JUSTICE, target);
                            }
                            if (target.Distance - target.CombatReach - 1 <= 10f && utils.CanCast(HAMMER_OF_JUSTICE))
                            {
                                utils.LogActivity(HAMMER_OF_JUSTICE, target.Name);
                                return utils.Cast(HAMMER_OF_JUSTICE, target);
                            }
                        }
                    }

                    if (ExtraUtilsSettings.Instance.movementEnabled && (!target.InLineOfSpellSight || !target.IsWithinMeleeRange))
                    {
                        movement.KingHealMove(target, movement.meelerange);
                    }

                    
                    EmpoweredSeal(enemies_count);
                    if (!talents.IsSelected(19) && ProtPaladinSettings.Instance.SealToUse == ProtPaladinSettings.SealType.AUTO)
                    {
                        if (Me.HealthPercent <= ProtPaladinSettings.Instance.ForceSealInsight_HP && !utils.isAuraActive(SEAL_OF_INSIGHT))
                        {
                            //utils.LogActivity("AOE FALSE enemy:" + utils.EnemyMeleeUnits.Count());
                            utils.LogActivity(SEAL_OF_INSIGHT);
                            return utils.Cast(SEAL_OF_INSIGHT);
                        }
                    }
                    //if (Me.CurrentHolyPower < 5)
                    //{
                        if (AOE && target.IsWithinMeleeRange && utils.CanCast(HAMMER_OF_RIGHTEOUS))
                        {
                            utils.LogActivity(HAMMER_OF_RIGHTEOUS, target.Name);
                            return utils.Cast(HAMMER_OF_RIGHTEOUS, target);
                        }
                        if ((AOE || talents.IsSelected(14)) && utils.CanCast(HOLY_WRATH) && utils.AllAttaccableEnemyMobsInRange(10f).Count() >= 1)
                        {
                            utils.LogActivity(HOLY_WRATH);
                            return utils.Cast(HOLY_WRATH);
                        }                      
                        if (AOE && utils.CanCast(CONSECRATION))
                        {
                            if (ConsecratorGlyph || (!ConsecrationGlyph && target.IsWithinMeleeRange))
                            {
                                utils.LogActivity(CONSECRATION);
                                return utils.Cast(CONSECRATION);
                            }
                            if (ConsecrationGlyph)
                            {
                                WoWUnit ConsecrationCandidateTarget = utils.EnemyInRangeWithMobsAround(25f, 8f, 2, false, ExtraUtilsSettings.Instance.provinGround_Targeting);
                                if (ConsecrationCandidateTarget == null)
                                    ConsecrationCandidateTarget = target;
                                utils.LogActivity(CONSECRATION, ConsecrationCandidateTarget.SafeName);
                                utils.Cast(CONSECRATION);
                                SpellManager.ClickRemoteLocation(ConsecrationCandidateTarget.Location);
                                return true;
                            }
                        }
                        if (talents.IsSelected(19) && utils.CanCast(JUDGEMENT))
                        {
                            utils.LogActivity(JUDGEMENT, target.Name);
                            return utils.Cast(JUDGEMENT, target);
                        } 
                        if (utils.CanCast(HAMMER_OF_WRATH, target))
                        {
                            utils.LogActivity(HAMMER_OF_WRATH, target.Name);
                            return utils.Cast(HAMMER_OF_WRATH, target);
                        }
                        if (!AOE && target.IsWithinMeleeRange && utils.CanCast(CRUSADER_STRIKE))
                        {
                            utils.LogActivity(CRUSADER_STRIKE, target.Name);
                            return utils.Cast(CRUSADER_STRIKE, target);
                        }
                        if (utils.CanCast(JUDGEMENT))
                        {
                            utils.LogActivity(JUDGEMENT, target.Name);
                            return utils.Cast(JUDGEMENT, target);
                        }
                    //}

                    if (utils.CanCast(SERAPHIM) && target.IsWithinMeleeRange)
                    {
                        utils.LogActivity(SERAPHIM);
                        return utils.Cast(SERAPHIM);
                    }

                    if (!utils.CanCast(SERAPHIM))
                    {
                        if (utils.CanCast(AVENGERS_SHIELD))
                        {
                            utils.LogActivity(AVENGERS_SHIELD, target.Name);
                            return utils.Cast(AVENGERS_SHIELD, target);
                        }
                        if (utils.CanCast(EXECUTION_SENTENCE))
                        {
                            utils.LogActivity(EXECUTION_SENTENCE, target.Name);
                            return utils.Cast(EXECUTION_SENTENCE, target);
                        }
                        if (utils.CanCast(HOLY_PRISM))
                        {
                            utils.LogActivity(HOLY_PRISM, target.Name);
                            return utils.Cast(HOLY_PRISM, target);
                        }
                        if (utils.CanCast(LIGHTS_HAMMER))
                        {
                            WoWUnit LightHammerCandidateTarget = utils.EnemyInRangeWithMobsAround(30f, 10f, 2, false, ExtraUtilsSettings.Instance.provinGround_Targeting);
                            if (LightHammerCandidateTarget == null)
                                LightHammerCandidateTarget = target;
                            utils.LogActivity(LIGHTS_HAMMER, LightHammerCandidateTarget.Name);
                            utils.Cast(LIGHTS_HAMMER);
                            SpellManager.ClickRemoteLocation(LightHammerCandidateTarget.Location);
                            return true;
                            
                        }
                        if (target.IsWithinMeleeRange && utils.CanCast(SHIELD_OF_RIGHTEOUS)
                            && (!talents.IsSelected(20) || utils.isAuraActive(SERAPHIM) || Me.CurrentHolyPower == 5)
                            )
                        {
                            utils.LogActivity(SHIELD_OF_RIGHTEOUS, target.Name);
                            return utils.Cast(SHIELD_OF_RIGHTEOUS, target);
                        }
                        if (utils.CanCast(HOLY_WRATH) && utils.AllAttaccableEnemyMobsInRange(10f).Count() >= 1)
                        {
                            utils.LogActivity(HOLY_WRATH);
                            return utils.Cast(HOLY_WRATH);
                        }
                        if (utils.CanCast(CONSECRATION))
                        {
                            if (ConsecratorGlyph || (!ConsecrationGlyph && target.IsWithinMeleeRange))
                            {
                                utils.LogActivity(CONSECRATION);
                                return utils.Cast(CONSECRATION);
                            }
                            if (ConsecrationGlyph)
                            {
                                WoWUnit ConsecrationCandidateTarget = utils.EnemyInRangeWithMobsAround(25f, 8f, 2, false, ExtraUtilsSettings.Instance.provinGround_Targeting);
                                if (ConsecrationCandidateTarget == null)
                                    ConsecrationCandidateTarget = target;
                                utils.LogActivity(CONSECRATION, ConsecrationCandidateTarget.SafeName);
                                utils.Cast(CONSECRATION);
                                SpellManager.ClickRemoteLocation(ConsecrationCandidateTarget.Location);
                                return true;
                            }
                        }
                    }
                }
            }
            else
            {
                //other healer spells used above
                if (Me.HealthPercent < 80 && utils.CanCast(FLASH_OF_LIGHT))
                {
                    utils.LogActivity("Hand of Protection active:" + FLASH_OF_LIGHT, Me.SafeName);
                    return utils.Cast(FLASH_OF_LIGHT, Me);
                }
            }
            #endregion

            #region Seal cast

            if (!talents.IsSelected(19) && ProtPaladinSettings.Instance.SealToUse == ProtPaladinSettings.SealType.AUTO)
            {
                if (enemies_count >= ProtPaladinSettings.Instance.Seal_of_righteouness_count && Me.HealthPercent > ProtPaladinSettings.Instance.ForceSealInsight_HP && !utils.isAuraActive(SEAL_OF_RIGHTEOUSNESS))
                {
                    utils.LogActivity(SEAL_OF_RIGHTEOUSNESS);
                    return utils.Cast(SEAL_OF_RIGHTEOUSNESS);
                }
                else if (Me.HealthPercent <= ProtPaladinSettings.Instance.ForceSealInsight_HP && !utils.isAuraActive(SEAL_OF_INSIGHT))
                {
                    utils.LogActivity(SEAL_OF_INSIGHT);
                    return utils.Cast(SEAL_OF_INSIGHT);
                }
            }
            else if (ProtPaladinSettings.Instance.SealToUse == ProtPaladinSettings.SealType.INSIGHT &&
                !utils.isAuraActive(SEAL_OF_INSIGHT))
            {
                utils.LogActivity(SEAL_OF_INSIGHT);
                return utils.Cast(SEAL_OF_INSIGHT);
            }
            else if (ProtPaladinSettings.Instance.SealToUse == ProtPaladinSettings.SealType.RIGHTEOUSNESS &&
                !utils.isAuraActive(SEAL_OF_RIGHTEOUSNESS))
            {
                utils.LogActivity(SEAL_OF_RIGHTEOUSNESS);
                return utils.Cast(SEAL_OF_RIGHTEOUSNESS);
            }
            #endregion

            return false;
           
        }

        private bool Resurrect()
        {
            foreach (WoWPlayer player in utils.GetResurrectTargets(40f))
            {
                if (Blacklist.Contains(player.Guid, BlacklistFlags.All)) continue;
                else
                {
                    if (player.Distance > 40 || !player.InLineOfSpellSight) return false;
                    else if (utils.CanCast(RESURRECTION, player) && ProtPaladinSettings.Instance.UseRedemption && !Me.IsMoving)
                    {
                        utils.LogActivity(RESURRECTION, player.SafeName);
                        Blacklist.Add(player, BlacklistFlags.All,new TimeSpan(0, 0, 60));
                        return utils.Cast(RESURRECTION, player);
                    }

                    return false;
                }
            }

            return false;
        }
    }
}
